<template>
  <div :class="[prefixCls, `${prefixCls}--${configGlobal.size}`]">
    <el-input v-model="inputValue" :type="inputType" v-bind="$attrs">
      <template #suffix>
        <Icon
          :icon="inputIconName"
          class="el-input__icon cursor-pointer"
          @click="changeInputType"
        />
      </template>
    </el-input>
    <div v-if="strength" :class="`${prefixCls}__bar`" class="relative mb-6px mt-10px mx-auto h-6px">
      <div :class="`${prefixCls}__bar--fill`" :data-score="passwordStrength"></div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { propTypes } from '@/utils/propTypes'
import { useDesign } from '@/hooks/web/useDesign'
import { useConfigGlobal } from '@/hooks/web/useConfigGlobal'
import type { ZxcvbnResult } from '@zxcvbn-ts/core'
import { zxcvbn } from '@zxcvbn-ts/core'

defineOptions({ name: 'InputPassword' })

const { getPrefixCls } = useDesign()
const prefixCls = getPrefixCls('input-password')

const props = defineProps({
  // 是否显示密码强度
  strength: propTypes.bool.def(false),
  modelValue: propTypes.string.def('')
})

watch(
  () => props.modelValue,
  (val: string) => {
    inputValue.value = val
  }
)

const { configGlobal } = useConfigGlobal()

const emit = defineEmits(['update:modelValue'])

const inputType = ref<'password' | 'text'>('password')
const changeInputType = () => {
  inputType.value = inputType.value === 'password' ? 'text' : 'password'
}

const inputValue = ref(props.modelValue)

watch(
  () => inputValue.value,
  (val: string) => {
    emit('update:modelValue', val)
  }
)

// 获取密码强度
const passwordStrength = computed(() => {
  return inputValue.value ? (zxcvbn(inputValue.value) as ZxcvbnResult).score : -1
})

const inputIconName = computed(() => (inputType.value === 'password' ? 'ep:hide' : 'ep:view'))
</script>

<style scoped lang="scss">
$prefix-cls: #{$namespace}-input-password;

.#{$prefix-cls} {
  :deep(.#{$elNamespace}-input__clear) {
    margin-left: 5px;
  }

  &__bar {
    background-color: var(--el-text-color-disabled);
    border-radius: var(--el-border-radius-base);

    &::before,
    &::after {
      position: absolute;
      z-index: 10;
      display: block;
      width: 20%;
      height: inherit;
      background-color: transparent;
      border-color: var(--el-color-white);
      border-style: solid;
      border-width: 0 5px;
      content: '';
    }

    &::before {
      left: 20%;
    }

    &::after {
      right: 20%;
    }

    &--fill {
      position: absolute;
      width: 0;
      height: inherit;
      background-color: transparent;
      border-radius: inherit;
      transition:
        width 0.5s ease-in-out,
        background 0.25s;

      &[data-score='0'] {
        width: 20%;
        background-color: var(--el-color-danger);
      }

      &[data-score='1'] {
        width: 40%;
        background-color: var(--el-color-danger);
      }

      &[data-score='2'] {
        width: 60%;
        background-color: var(--el-color-warning);
      }

      &[data-score='3'] {
        width: 80%;
        background-color: var(--el-color-success);
      }

      &[data-score='4'] {
        width: 100%;
        background-color: var(--el-color-success);
      }
    }
  }

  &--mini > &__bar {
    border-radius: var(--el-border-radius-small);
  }
}
</style>
